<?php

/**
 * JingYao-backend
 *
 * @link     https://gitee.com/wang-zhihui-release/jingyao-backend
 * @apiDocument https://gitee.com/wang-zhihui-release/jingyao-backend/wikis/
 */

namespace App\Services;

use App\Enums\AdminActionTypeEnum;
use App\Exceptions\ApiException;
use App\Format\MessageFormat;
use App\Models\Message;
use App\Models\UserMessageLog;

class MessageService
{
    public function getList(int $page, int $pageSize, string $orderColumn, string $orderType, array $search): array
    {
        $userId = $search['user_id'];
        $token = $search['token'];
        $userService = new UserService();
        $isLogin = $userService->checkLogin($userId, $token);

        $builder = Message::query()->where('push_time', '<', time());

        $filterUserIds = [0];
        if ($isLogin) {
            array_push($filterUserIds, $userId);
        }

        $builder->whereIn('user_id', $filterUserIds);

        if (isset($search['title'])) {
            $builder->where('title', 'like', '%' . $search['title'] . '%');
        }
        if (isset($search['start_date'], $search['end_date'])) {
            $builder->where('push_time', '>=', strtotime($search['start_date']));
            if (strlen($search['end_date']) > 10) {
                $builder->where('push_time', '<=', strtotime($search['end_date']));
            } else {
                $builder->where('push_time', '<=', strtotime($search['end_date']) + (24 * 3600));
            }
        }
        if (isset($search['start_date']) && ! isset($search['end_date'])) {
            $builder->where('push_time', '>=', strtotime($search['start_date']));
        }
        if (! isset($search['start_date']) && isset($search['end_date'])) {
            if (strlen($search['end_date']) > 10) {
                $builder->where('push_time', '<=', strtotime($search['end_date']));
            } else {
                $builder->where('push_time', '<=', strtotime($search['end_date']) + (24 * 3600));
            }
        }
        $count = $builder->count();
        $list = $builder
            ->with('userReadLog', function ($query) use ($userId) {
                $query->whereIn('user_id', [0, $userId]);
            })
            ->skip(($page - 1) * $pageSize)
            ->take($pageSize)
            ->orderBy($orderColumn, $orderType)
            ->get()->toArray();

        foreach ($list as &$message) {
            if (! $isLogin) {
                $message['is_read'] = false;
                continue;
            }
            if (empty($message['user_read_log'])) {
                $message['is_read'] = false;
            } else {
                $message['is_read'] = true;
            }
        }

        return [
            'list' => $list,
            'page' => $page,
            'page_size' => $pageSize,
            'count' => $count,
        ];
    }

    public function getAdminList(int $page, int $pageSize, array $search)
    {
        $builder = Message::query()->where('user_id', 0);

        if (isset($search['title'])) {
            $builder->where('title', 'like', '%' . $search['title'] . '%');
        }
        if (isset($search['start_date'], $search['end_date'])) {
            $builder->where('push_time', '>=', strtotime($search['start_date']));
            $builder->where('push_time', '<=', strtotime($search['end_date']) + (24 * 3600));
        }
        if (isset($search['start_date']) && ! isset($search['end_date'])) {
            $builder->where('push_time', '>=', strtotime($search['start_date']));
        }
        if (! isset($search['start_date']) && isset($search['end_date'])) {
            $builder->where('push_time', '<=', strtotime($search['end_date']) + (24 * 3600));
        }
        $count = $builder->count();
        $list = $builder->skip(($page - 1) * $pageSize)
            ->take($pageSize)
            ->orderByDesc('id')
            ->get()->toArray();

        return [
            'list' => $list,
            'page' => $page,
            'page_size' => $pageSize,
            'count' => $count,
        ];
    }

    public function createMessage(MessageFormat $messageFormat)
    {
        $message = Message::query()->create($messageFormat->toArrayNotNull());
        adminLog($message, AdminActionTypeEnum::CREATE, '创建消息');
        return true;
    }

    public function updateMessage(MessageFormat $messageFormat)
    {
        $message = Message::query()->find($messageFormat->getId());
        if (empty($message)) {
            throw new ApiException('消息不存在', 1);
        }
        $data = $messageFormat->toArrayNotNull();
        unset($data['id']);
        $message->update($data);
        adminLog($message, AdminActionTypeEnum::UPDATE, '修改系统消息');
        return true;
    }

    public function delete(int $id)
    {
        $message = Message::query()->find($id);
        adminLog($message, AdminActionTypeEnum::DELETE, '删除消息');
        $message->delete();
        return true;
    }

    public function detail(int $id, ?int $userId, ?string $token)
    {
        $userService = new UserService();
        $isLogin = $userService->checkLogin($userId ?? 0, $token ?? '');
        if ($isLogin) {
            UserMessageLog::query()->firstOrCreate([
                'user_id' => $userId,
                'message_id' => $id,
            ], [
                'read_time' => time(),
            ]);
        }
        return Message::query()->find($id);
    }

    public function checkHaveNotReadMessage(int $userId)
    {
        $needReadMessageCount = Message::query()
            ->whereIn('user_id', [0, $userId])
            ->count();

        $readedMessageCount = UserMessageLog::query()
            ->where('user_id', $userId)
            ->count();

        return [
            'has_red' => $needReadMessageCount > $readedMessageCount,
            'number' => $needReadMessageCount - $readedMessageCount,
        ];
    }
}
